import numpy as np
from PySide6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QPushButton, 
                            QComboBox, QCheckBox, QLabel, QGroupBox, QWidget, 
                            QSplitter, QFrame, QSpinBox)
from PySide6.QtCore import Qt, Signal, QThread
import pyqtgraph as pg


class FFTDisplayWindow(QDialog):
    """FFT频谱显示窗口"""
    
    # 信号定义
    update_fft_signal = Signal(tuple, tuple, dict)  # 频率数据, 幅度数据, 参数
    window_closed = Signal(str)  # 窗口关闭信号，传递节点ID
    
    def __init__(self, processor=None, parent=None):
        super().__init__(parent)
        self.processor = processor
        self.setWindowTitle("频谱查看器")
        self.resize(800, 600)
        
        # 当前频谱数据
        self.current_frequencies = []
        self.current_magnitude = []
        self.current_parameters = {}
        
        # 获取节点ID（从处理器或节点名称中提取）
        self.node_id = getattr(processor, 'nodeId', "FFT查看器")
        
        # 最后更新时间（用于限制刷新率）
        self.last_update_time = 0
        
        # 初始化UI
        self.init_ui()
        
        # 连接信号槽
        self.update_fft_signal.connect(self.update_fft_display)
        
        # 应用深色主题（与波形查看器保持一致）
        self.apply_dark_theme()
        
        # 应用应用程序样式表（如果有父窗口）
        if parent:
            self.setStyleSheet(parent.styleSheet())
        
        # 处理器回调
        if self.processor:
            self.setup_processor_callbacks()
    
    def init_ui(self):
        """初始化用户界面"""
        main_layout = QVBoxLayout(self)
        
        # 创建分割器
        splitter = QSplitter(Qt.Vertical)
        
        # 频谱显示区域
        self.fft_widget = pg.PlotWidget()
        self.fft_plot = self.fft_widget.plot()
        
        # 配置坐标轴
        self.fft_widget.setLabel('bottom', '频率 (Hz)')
        self.fft_widget.setLabel('left', '幅度')
        self.fft_widget.showGrid(x=True, y=True)
        
        # 初始化频谱显示
        self.fft_widget.setTitle("频谱分析")
        self.fft_widget.setBackground('k')
        
        # 添加频谱图到分割器
        splitter.addWidget(self.fft_widget)
        
        # 控制面板
        control_panel = self.create_control_panel()
        splitter.addWidget(control_panel)
        
        # 设置分割器比例
        splitter.setSizes([400, 200])
        
        main_layout.addWidget(splitter)
        
        # 底部状态栏
        self.status_bar = QLabel("就绪")
        main_layout.addWidget(self.status_bar)
    
    def create_control_panel(self):
        """创建控制面板"""
        panel_widget = QWidget()
        panel_layout = QVBoxLayout(panel_widget)
        
        # FFT参数组
        fft_params_group = QGroupBox("FFT参数")
        fft_params_layout = QHBoxLayout()
        
        # FFT大小
        fft_params_layout.addWidget(QLabel("FFT大小:"))
        self.fft_size_combo = QComboBox()
        self.fft_size_combo.addItems(["256", "512", "1024", "2048", "4096"])
        self.fft_size_combo.currentTextChanged.connect(lambda text: self.on_parameter_change('fft_size', int(text)))
        fft_params_layout.addWidget(self.fft_size_combo)
        
        # 窗函数
        fft_params_layout.addWidget(QLabel("窗函数:"))
        self.window_type_combo = QComboBox()
        self.window_type_combo.addItems(["rectangular", "hann", "hamming", "blackman"])
        self.window_type_combo.currentTextChanged.connect(lambda text: self.on_parameter_change('window_type', text))
        fft_params_layout.addWidget(self.window_type_combo)
        
        # 幅度刻度
        fft_params_layout.addWidget(QLabel("幅度刻度:"))
        self.magnitude_scale_combo = QComboBox()
        self.magnitude_scale_combo.addItems(["linear", "log"])
        self.magnitude_scale_combo.currentTextChanged.connect(self._on_magnitude_scale_changed)
        fft_params_layout.addWidget(self.magnitude_scale_combo)
        
        # 频率刻度
        fft_params_layout.addWidget(QLabel("频率刻度:"))
        self.frequency_scale_combo = QComboBox()
        self.frequency_scale_combo.addItems(["linear", "log"])
        self.frequency_scale_combo.currentTextChanged.connect(self._on_frequency_scale_changed)
        fft_params_layout.addWidget(self.frequency_scale_combo)
        
        fft_params_group.setLayout(fft_params_layout)
        panel_layout.addWidget(fft_params_group)
        
        # 显示选项组
        display_group = QGroupBox("显示选项")
        display_layout = QHBoxLayout()
        
        # 自动缩放
        self.auto_scale_check = QCheckBox("自动缩放")
        self.auto_scale_check.setChecked(True)
        self.auto_scale_check.toggled.connect(lambda checked: self.on_parameter_change('auto_scale', checked))
        display_layout.addWidget(self.auto_scale_check)
        
        # 显示网格
        self.show_grid_check = QCheckBox("显示网格")
        self.show_grid_check.setChecked(True)
        self.show_grid_check.toggled.connect(lambda checked: self.on_parameter_change('show_grid', checked))
        display_layout.addWidget(self.show_grid_check)
        
        # 频率范围（目前作为UI元素预留）
        display_layout.addWidget(QLabel("频率范围:"))
        self.freq_range_combo = QComboBox()
        self.freq_range_combo.addItems(["1k", "5k", "10k", "20k"])
        # 映射到实际频率值
        self.freq_range_mapping = {
            "1k": 1000,
            "5k": 5000,
            "10k": 10000,
            "20k": 22050
        }
        self.freq_range_combo.currentTextChanged.connect(
            lambda text: self.on_parameter_change('frequency_range', self.freq_range_mapping.get(text, 22050)))
        display_layout.addWidget(self.freq_range_combo)
        
        # 刷新率设置
        display_layout.addWidget(QLabel("刷新率:"))
        self.refresh_rate_spin = QSpinBox()
        self.refresh_rate_spin.setRange(5, 20)  # 设置范围为5-20 FPS
        self.refresh_rate_spin.setValue(5)  # 默认值为5 FPS
        self.refresh_rate_spin.setSingleStep(1)
        self.refresh_rate_spin.setSuffix(" FPS")
        self.refresh_rate_spin.valueChanged.connect(lambda value: self.on_parameter_change('refresh_rate', value))
        display_layout.addWidget(self.refresh_rate_spin)
        
        display_group.setLayout(display_layout)
        panel_layout.addWidget(display_group)
        
        # 操作按钮组
        buttons_layout = QHBoxLayout()
        
        self.reset_button = QPushButton("重置")
        self.reset_button.clicked.connect(self.reset_view)
        buttons_layout.addWidget(self.reset_button)
        
        self.export_button = QPushButton("导出图像")
        self.export_button.clicked.connect(self.export_image)
        buttons_layout.addWidget(self.export_button)
        
        buttons_layout.addStretch()
        panel_layout.addLayout(buttons_layout)
        
        return panel_widget
    
    def apply_dark_theme(self):
        """应用深色主题"""
        # 设置PyQtGraph的主题
        pg.setConfigOptions(antialias=True)
        pg.setConfigOption('background', 'k')
        pg.setConfigOption('foreground', 'd')
        
        # 应用主题到频谱图
        if hasattr(self, 'fft_widget'):
            self.fft_widget.setBackground('k')
            
            # 设置坐标轴样式
            self.fft_widget.getAxis('bottom').setPen(color=(200, 200, 200))
            self.fft_widget.getAxis('left').setPen(color=(200, 200, 200))
            self.fft_widget.getAxis('bottom').setTextPen(color=(200, 200, 200))
            self.fft_widget.getAxis('left').setTextPen(color=(200, 200, 200))
            
            # 设置频谱线样式
            self.fft_plot.setPen(color=(0, 255, 255), width=2)
        
        # 设置窗口背景和文本颜色
        self.setStyleSheet("""
            QDialog {
                background-color: #2b2b2b;
                color: #ffffff;
            }
            QLabel {
                color: #ffffff;
            }
            QGroupBox {
                color: #ffffff;
                border: 1px solid #555555;
                border-radius: 5px;
                margin-top: 1ex;
                font-weight: bold;
                background-color: #353535;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                subcontrol-position: top center;
                padding: 0 5px;
                background-color: #353535;
                color: #ffffff;
            }
            QComboBox, QCheckBox, QPushButton {
                color: #ffffff;
                background-color: #454545;
                border: 1px solid #555555;
            }
            QPushButton:hover {
                background-color: #606060;
            }
        """)
    
    def setup_processor_callbacks(self):
        """设置处理器回调"""
        if self.processor:
            # 从处理器获取初始参数
            self.auto_scale_check.setChecked(getattr(self.processor, 'auto_scale', True))
            self.fft_size_combo.setCurrentText(str(getattr(self.processor, 'fft_size', 1024)))
            self.window_type_combo.setCurrentText(getattr(self.processor, 'window_type', 'hann'))
            self.magnitude_scale_combo.setCurrentText(getattr(self.processor, 'magnitude_scale', 'log'))
            self.frequency_scale_combo.setCurrentText(getattr(self.processor, 'frequency_scale', 'linear'))
            self.show_grid_check.setChecked(getattr(self.processor, 'show_grid', True))
            self.refresh_rate_spin.setValue(getattr(self.processor, 'refresh_rate', 5))
            
            # 设置频率范围
            freq_range = getattr(self.processor, 'frequency_range', 22050)
            for text, value in self.freq_range_mapping.items():
                if abs(value - freq_range) < 1000:
                    self.freq_range_combo.setCurrentText(text)
                    break
    
    def update_fft_display(self, frequencies, magnitude, params):
        """更新频谱显示"""
        try:
            # 更新当前数据
            self.current_frequencies = frequencies
            self.current_magnitude = magnitude
            self.current_parameters.update(params)
            
            # 更新频谱图
            if frequencies and magnitude:
                self.fft_plot.setData(frequencies, magnitude)
                
                # 根据自动缩放设置调整视图范围
                if params.get('auto_scale', True):
                    # 根据频率刻度设置X轴模式
                    frequency_scale = params.get('frequency_scale', 'linear')
                    magnitude_scale = params.get('magnitude_scale', 'log')
                    
                    # 设置坐标轴对数/线性模式
                    self.fft_widget.setLogMode(x=(frequency_scale == 'log'), y=(magnitude_scale == 'log'))
                    
                    # 设置X轴范围
                    if frequency_scale == 'log':
                        # 对数模式下，最小值不能为0
                        min_freq = 1.0
                        max_freq = params.get('frequency_range', 22050)
                        self.fft_widget.setXRange(min_freq, max_freq)
                    else:
                        # 线性模式
                        self.fft_widget.setXRange(0, params.get('frequency_range', 22050))
                    
                    # 根据幅度刻度调整Y轴范围
                    if magnitude_scale == 'log':
                        # dB范围
                        min_db = max(-100, min(magnitude) - 10)
                        max_db = min(0, max(magnitude) + 10)
                        self.fft_widget.setYRange(min_db, max_db)
                    else:
                        # 线性范围
                        self.fft_widget.setYRange(0, max(magnitude) * 1.1)
                
                # 更新网格显示
                self.fft_widget.showGrid(x=params.get('show_grid', True), 
                                        y=params.get('show_grid', True))
                
                # 更新状态栏
                self.status_bar.setText(f"FFT大小: {params.get('fft_size', 1024)}, "
                                      f"窗函数: {params.get('window_type', 'hann')}, "
                                      f"采样率: {params.get('sample_rate', 44100)}Hz")
        except Exception as e:
            print(f"更新频谱显示时出错: {e}")
    
    def _on_magnitude_scale_changed(self, text):
        """处理幅度刻度变化，更新Y轴模式"""
        # 获取当前频率刻度设置
        frequency_scale = self.frequency_scale_combo.currentText()
        # 立即设置Y轴模式，保持X轴模式不变
        self.fft_widget.setLogMode(x=(frequency_scale == 'log'), y=(text == 'log'))
        # 更新参数
        self.on_parameter_change('magnitude_scale', text)
        
    def _on_frequency_scale_changed(self, text):
        """处理频率刻度变化，更新X轴模式"""
        # 获取当前幅度刻度设置
        magnitude_scale = self.magnitude_scale_combo.currentText()
        # 立即设置X轴模式，保持Y轴模式不变
        self.fft_widget.setLogMode(x=(text == 'log'), y=(magnitude_scale == 'log'))
        # 更新参数
        self.on_parameter_change('frequency_scale', text)
        
    def on_parameter_change(self, param_name, value):
        """处理参数变化"""
        # 更新处理器参数
        if self.processor and hasattr(self.processor, 'update_parameter_from_display'):
            self.processor.update_parameter_from_display(param_name, value)
    
    def on_processor_parameters_updated(self, new_parameters):
        """当处理器参数更新时被调用"""
        # 更新UI控件
        if 'auto_scale' in new_parameters:
            self.auto_scale_check.setChecked(new_parameters['auto_scale'])
        if 'fft_size' in new_parameters:
            self.fft_size_combo.setCurrentText(str(new_parameters['fft_size']))
        if 'window_type' in new_parameters:
            self.window_type_combo.setCurrentText(new_parameters['window_type'])
        if 'magnitude_scale' in new_parameters:
            self.magnitude_scale_combo.setCurrentText(new_parameters['magnitude_scale'])
        if 'frequency_scale' in new_parameters:
            self.frequency_scale_combo.setCurrentText(new_parameters['frequency_scale'])
        if 'frequency_range' in new_parameters:
            freq_range = new_parameters['frequency_range']
            for text, value in self.freq_range_mapping.items():
                if abs(value - freq_range) < 1000:
                    self.freq_range_combo.setCurrentText(text)
                    break
        if 'show_grid' in new_parameters:
            self.show_grid_check.setChecked(new_parameters['show_grid'])
    
    def reset_view(self):
        """重置视图"""
        if hasattr(self, 'fft_widget'):
            # 获取当前刻度设置
            frequency_scale = self.current_parameters.get('frequency_scale', 'linear')
            magnitude_scale = self.current_parameters.get('magnitude_scale', 'log')
            
            # 设置坐标轴模式
            self.fft_widget.setLogMode(x=(frequency_scale == 'log'), y=(magnitude_scale == 'log'))
            
            # 设置X轴范围
            if frequency_scale == 'log':
                self.fft_widget.setXRange(1.0, self.current_parameters.get('frequency_range', 22050))
            else:
                self.fft_widget.setXRange(0, self.current_parameters.get('frequency_range', 22050))
            
            # 设置Y轴范围
            if magnitude_scale == 'log':
                self.fft_widget.setYRange(-100, 0)
            else:
                self.fft_widget.setYRange(0, 1.0)
    
    def export_image(self):
        """导出当前频谱图"""
        try:
            # 这里只是一个基础实现，实际项目中可能需要文件对话框选择保存路径
            filename = "fft_spectrum.png"
            self.fft_widget.scene().saveImage(filename, size=(800, 600))
            self.status_bar.setText(f"已导出图像到 {filename}")
        except Exception as e:
            self.status_bar.setText(f"导出图像失败: {e}")
    
    def closeEvent(self, event):
        """关闭窗口时的处理"""
        # 断开与处理器的连接
        if self.processor and hasattr(self.processor, 'set_display_window'):
            self.processor.set_display_window(None)
        
        # 发送窗口关闭信号
        self.window_closed.emit(self.node_id)
        
        event.accept()